package com.wh.wisdomsite.xbox.core.impl;

import com.wh.wisdomsite.xbox.common.*;
import com.wh.wisdomsite.xbox.common.annotation.HttpAction;
import com.wh.wisdomsite.xbox.common.annotation.MessageFormat;
import com.wh.wisdomsite.xbox.common.session.Session;
import com.wh.wisdomsite.xbox.common.error.MainError;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * 请求上下文,将请求中的所有信息都记录Context中
 * @Package com.wh.wisdomsite.xbox.common
 * @author 谢泽鹏
 * @date 2014年10月8日 下午4:02:14
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2014
 * @version V1.0
 */
public class DefaultXboxRequestContext implements XboxRequestContext {

    private static final Log logger = LogFactory.getLog(DefaultXboxRequestContext.class);

    /**
     * 服务方法
     */
    private String method;

    /**
     * 服务版本
     */
    private String version;

    /**
     * 数据格式[json, xml]
     */
    private String format;

    /**
     * 应用语言[zh_CN, en]
     */
    private Locale locale;

    /**
     * 应用Key
     */
    private String appKey;

    /**
     * sign签名
     */
    private String sign;

    /**
     * 业务参数
     */
    private String bindObject;

    /**
     * 会话编号
     */
    private String sessionId;

    /**
     * 调用方式[SYNC, ASYNC]
     */
    private String executionType;

    /**
     * 请求方式[POST, GET]
     */
    private HttpAction httpAction;

    /**
     * 客户端IP
     */
    private String ip;

    /**
     * 响应字符串
     */
    private String outPut;

    /**
     * 会话对象
     */
    private Session session;

    /**
     * 数据格式对象
     */
    private MessageFormat messageFormat;

    /**
     * HttpServletRequest请求对象
     */
    private HttpServletRequest servletRequest;

    /**
     * HttpServletResponse响应对象
     */
    private HttpServletResponse servletResponse;

    /**
     * xboxRequest请求对象
     */
    private XboxRequest xboxRequest;

    /**
     * 响应对象
     */
    private Object xboxResponse;

    /**
     * 参数集合
     */
    private Map<String, Object> attributes;

    /**
     * ServiceMethodHandler对象
     */
    private ServiceMethodHandler serviceMethodHandler;

    /**
     * xboxContext上下文
     */
    private XboxContext xboxContext;

    /**
     * 所有参数
     */
    private Map<String, String> allParams;

    /**
     * 系统异常
     */
    private Throwable throwable;

    /**
     * 错误信息
     */
    private MainError mainError;

    /**
     * 执行异常
     */
    private Exception exception;

    /**
     * 逻辑异常
     */
    private StringBuffer logicError;

    /**
     * 开始时间
     */
    private long beginTime;

    /**
     * 结束时间
     */
    private long endTime;

    /**
     * 服务端请求时间戳
     */
    private Long requestTimestamp;

    /**
     * 调用类型(ANDROID, IOS, WAP, PC)
     */
    private String callType;

    /**
     * 调用版本
     */
    private String callVersion;

    /**
     * 客户端平台类型
     */
    private String client;


    /**
     * 应用品牌
     */
    private String appBrand;

    /**
     * 应用信息
     */
    private String appBaseInfo;



    /**
     * 构造函数(初始化：获取服务调用：开始时间)
     */
    public DefaultXboxRequestContext() {
        this.beginTime = System.currentTimeMillis();
        logger.info("请求服务开始时间： " + this.beginTime);
    }

    /**
     * 构造函数(初始化：获取服务调用：开始时间)
     * @param xboxContext
     */
    public DefaultXboxRequestContext(XboxContext xboxContext) {
        this.xboxContext = xboxContext;
        this.attributes = new HashMap<String, Object>();
        this.beginTime = System.currentTimeMillis();
        logger.info("请求服务开始时间： " + this.beginTime);
    }

    /**
     * 是否正常运行结束
     * @return
     */
    @Override
    public boolean isSuccess() {
        return (throwable == null && mainError == null) ? true : false;
    }


    /**
     * 1. throwable【系统异常: 系统框架调度时，抛出系统异常错误信息】
     * 2. exception【执行异常: 系统框架执行时，抛出系统代码异常信息信息】
     * 3. loggerMsg【逻辑异常: 系统框架执行时，抛出系统逻辑异常错误信息】
     * @return
     */
    @Override
    public String getException() {
        if (null != throwable) {
            return getException(throwable);
        }
        if(null != exception){
            return getException(exception);
        }
        if(null != logicError){
            return getException(logicError);
        }
            return null;
    }


    /**
     * 获取详细异常信息
     * @param throwable
     * @return
     */
    public synchronized static String getException(Throwable throwable) {
        StringBuffer buffer = new StringBuffer();
        if(Throwable.class.equals(throwable.getClass())){
            buffer.append("##########throwable【系统异常: 系统框架调度时，抛出系统异常错误信息】##########\n");
        }
        if(Exception.class.equals(throwable.getClass())){
            buffer.append("##########exception【执行异常: 系统框架执行时，抛出系统代码异常信息信息】##########\n");
        }
        buffer.append("异常信息[getMessage]:");
        buffer.append("\n\t");
        buffer.append(throwable.getMessage());
        StackTraceElement[] stackTraceElements = throwable.getStackTrace();
        if (null != stackTraceElements) {
            buffer.append("\n");
            buffer.append("堆栈信息[getStackTrace]:");
            buffer.append("\n");
            for (StackTraceElement element : stackTraceElements) {
                buffer.append("\t" + element + "\n");
            }
        }
        return buffer.toString();
    }


    /**
     * 获取详细异常信息
     * @param logicError
     * @return
     */
    public synchronized static String getException(StringBuffer logicError) {
        StringBuffer buffer = new StringBuffer();
        buffer.append("##########logicError【逻辑异常: 系统框架执行时，抛出系统逻辑异常错误信息】##########\n");
        buffer.append("异常信息[getMessage]:");
        buffer.append("\n\t");
        buffer.append(logicError.toString());
        return buffer.toString();
    }


    @Override
    public String setException(Exception exception) {
        this.exception = exception;
        return null;
    }

    @Override
    public Throwable getThrowable() {
        return throwable;
    }

    @Override
    public void setThrowable(Throwable throwable) {
        this.throwable = throwable;
    }

    @Override
    public StringBuffer getLogicError() {
        return logicError;
    }

    @Override
    public void setLogicError(StringBuffer logicError) {
        this.logicError = logicError;
    }

    @Override
    public Session getSession() {
        if (xboxContext != null && xboxContext.getSessionManager() != null && getSessionId() != null && !"".equals(getSessionId())) {
            return xboxContext.getSessionManager().getSession(getSessionId());
        } else {
            return null;
        }
    }

    @Override
    public void addSession(String sessionId, Session session) {
        if (xboxContext != null && xboxContext.getSessionManager() != null) {
            xboxContext.getSessionManager().addSession(sessionId, session);
        }
    }

    @Override
    public void addSession(String sessionId, Session session, int expiredTime) {
        if (xboxContext != null && xboxContext.getSessionManager() != null) {
            xboxContext.getSessionManager().addSession(sessionId, session, expiredTime);
        }
    }

    @Override
    public void addSession(String sessionId, Session session, int expiredTime, String attrKey) {
        if (xboxContext != null && xboxContext.getSessionManager() != null) {
            xboxContext.getSessionManager().addSession(sessionId, session, expiredTime, attrKey);
        }
    }

    @Override
    public void addOtherSession(String sessionId, Session session, int expiredTime) {
        if (xboxContext != null && xboxContext.getSessionManager() != null) {
            xboxContext.getSessionManager().addOtherSession(sessionId, session, expiredTime);
        }
    }

    @Override
    public Session getOtherSession(String sessionId) {
        if (xboxContext != null && xboxContext.getSessionManager() != null && sessionId != null && !"".equals(sessionId)) {
            return xboxContext.getSessionManager().getOtherSession(sessionId);
        } else {
            return null;
        }
    }

    @Override
    public void removeSession() {
        if (xboxContext != null && xboxContext.getSessionManager() != null) {
            xboxContext.getSessionManager().removeSession(getSessionId());
        }
    }

    @Override
    public void removeOtherSesssion(String sessionId) {
        if (xboxContext != null && xboxContext.getSessionManager() != null) {
            xboxContext.getSessionManager().removeOtherSession(sessionId);
        }
    }

    @Override
    public String getSessionId() {
        return sessionId;
    }

    @Override
    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
    }

    @Override
    public boolean isSignEnable() {
        return xboxContext.isSignEnable() && !getServiceMethodHandler().getServiceMethodDefinition().isIgnoreSign();
    }

    @Override
    public String getMethodKey() {
        return ServiceMethodDefinition.methodWithVerion(method, version);
    }

    @Override
    public String getBindObject() {
        return bindObject;
    }

    @Override
    public void setBindObject(String bindObject) {
        this.bindObject = bindObject;
    }

    @Override
    public String getSign() {
        return sign;
    }

    @Override
    public void setSign(String sign) {
        this.sign = sign;
    }

    @Override
    public MessageFormat getMessageFormat() {
        return messageFormat;
    }

    @Override
    public void setMessageFormat(MessageFormat messageFormat) {
        this.messageFormat = messageFormat;
    }

    @Override
    public String getAppKey() {
        return appKey;
    }

    @Override
    public void setAppKey(String appKey) {
        this.appKey = appKey;
    }

    @Override
    public String getIp() {
        return ip;
    }

    @Override
    public void setIp(String ip) {
        this.ip = ip;
    }

    @Override
    public Map<String, String> getAllParams() {
        return allParams;
    }

    @Override
    public void setAllParams(Map<String, String> allParams) {
        this.allParams = allParams;
    }

    @Override
    public Object getXboxResponse() {
        return xboxResponse;
    }

    @Override
    public void setXboxResponse(Object xboxResponse) {
        this.xboxResponse = xboxResponse;
    }

    @Override
    public String getExecutionType() {
        return executionType;
    }

    @Override
    public void setExecutionType(String executionType) {
        this.executionType = executionType;
    }

    @Override
    public HttpAction getHttpAction() {
        return httpAction;
    }

    @Override
    public void setHttpAction(HttpAction httpAction) {
        this.httpAction = httpAction;
    }

    @Override
    public Locale getLocale() {
        return locale;
    }

    @Override
    public void setLocale(Locale locale) {
        this.locale = locale;
    }

    @Override
    public Object getAttribute(String name) {
        return attributes.get(name);
    }

    @Override
    public void setAttribute(String name, Object object) {
        this.attributes.put(name, object);
    }

    @Override
    public HttpServletRequest getServletRequest() {
        return servletRequest;
    }

    @Override
    public void setServletRequest(HttpServletRequest servletRequest) {
        this.servletRequest = servletRequest;
    }

    @Override
    public HttpServletResponse getServletResponse() {
        return servletResponse;
    }

    @Override
    public void setServletResponse(HttpServletResponse servletResponse) {
        this.servletResponse = servletResponse;
    }

    @Override
    public XboxRequest getXboxRequest() {
        return xboxRequest;
    }

    @Override
    public void setXboxRequest(XboxRequest xboxRequest) {
        this.xboxRequest = xboxRequest;
    }

    @Override
    public XboxContext getXboxContext() {
        return xboxContext;
    }

    @Override
    public void setXboxContext(XboxContext xboxContext) {
        this.xboxContext = xboxContext;
    }

    @Override
    public ServiceMethodHandler getServiceMethodHandler() {
        return serviceMethodHandler;
    }

    @Override
    public void setServiceMethodHandler(ServiceMethodHandler serviceMethodHandler) {
        this.serviceMethodHandler = serviceMethodHandler;
    }

    @Override
    public String getMethod() {
        return method;
    }

    @Override
    public void setMethod(String method) {
        this.method = method;
    }

    @Override
    public String getFormat() {
        return format;
    }

    @Override
    public void setFormat(String format) {
        this.format = format;
    }

    @Override
    public String getVersion() {
        return version;
    }

    @Override
    public void setVersion(String version) {
        this.version = version;
    }

    @Override
    public MainError getMainError() {
        return mainError;
    }

    @Override
    public void setMainError(MainError mainError) {
        this.mainError = mainError;
    }

    @Override
    public long getBeginTime() {
        return beginTime;
    }

    @Override
    public void setBeginTime(long beginTime) {
        this.beginTime = beginTime;
    }

    @Override
    public long getEndTime() {
        return endTime;
    }

    @Override
    public void setEndTime(long endTime) {
        this.endTime = endTime;
    }

    @Override
    public long getDuration() {
        return endTime - beginTime;
    }

    @Override
    public String getOutPut() {
        return outPut;
    }

    @Override
    public void setOutPut(String outPut) {
        this.outPut = outPut;
    }

    @Override
    public Long getRequestTimestamp() {
        return this.requestTimestamp;
    }

    @Override
    public void setRequestTimestamp(Long requestTimestamp) {
        this.requestTimestamp = requestTimestamp;
    }

    @Override
    public String getCallType() {
        return this.callType;
    }

    @Override
    public void setCallType(String callType) {
        this.callType = callType;
    }

    @Override
    public String getCallVersion() {
        return this.callVersion;
    }

    @Override
    public void setCallVersion(String callVersion) {
         this.callVersion = callVersion;
    }

    @Override
    public String getClient() {
        return this.client;
    }

    @Override
    public void setClient(String client) {
        this.client = client;
    }

    @Override
    public String getAppBrand() {
        return this.appBrand;
    }

    @Override
    public void setAppBrand(String appBrand) {
        this.appBrand = appBrand;
    }

    @Override
    public String getAppBaseInfo() {
        return this.appBaseInfo;
    }

    @Override
    public void setAppBaseInfo(String appBaseInfo) {
        this.appBaseInfo = appBaseInfo;
    }


}
